package org.spbu.ir.dictionary.diskdic;

import java.nio.channels.FileChannel;
import java.nio.MappedByteBuffer;
import java.io.File;
import java.io.RandomAccessFile;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;

/**
 * Created by IntelliJ IDEA.
 * User: im203768
 * Date: 02.04.2007
 * Time: 17:55:09
 * To change this template use File | Settings | File Templates.
 */
public class ABCLinkedList {
    private final ABC abc;

    private FileChannel dataChanell;
    private static final int SIZE = Long.SIZE/8;
    long[] byteMap;

    public ABCLinkedList(File file, ABC abc) throws IOException {
        this.abc = abc;
        byteMap = new long[abc.length()];
        if(!file.exists())
            init(file);
        else
            read(file);
    }

    private void read(File file) throws IOException {
        dataChanell = new RandomAccessFile(file, "rw").getChannel();
        MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, 0, SIZE * abc.length());
        for(int i = 0; i < abc.length(); i++)
            byteMap[i] = buffer.getLong();
    }

    private void init(File file) throws IOException {
        dataChanell = new RandomAccessFile(file, "rw").getChannel();
        MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, 0, SIZE * abc.length());
        for(int i = 0; i < abc.length(); i++)
            buffer.putLong(0L);
        Arrays.fill(byteMap, 0L);
        buffer.force();
    }

    public void addPossition(String firstLetter, long position) throws IOException {
        long next = byteMap[abc.indexOf(firstLetter)];
        long prev = -1; 
        while(next != 0L){
            MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_ONLY, next, SIZE * 2);
            prev = next;
            next = buffer.getLong();
        }
        if(prev < 0){
            long l = dataChanell.size();
            MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, l, SIZE * 2);
            buffer.putLong(0L);
            buffer.putLong(position);
            buffer.force();
            byteMap[abc.indexOf(firstLetter)] = l;
            buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, abc.indexOf(firstLetter) * SIZE, SIZE);
            buffer.putLong(l);
            buffer.force();
            return;
        }
        long l = dataChanell.size();
        MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, l, SIZE * 2);
        buffer.putLong(0L);
        buffer.putLong(position);
        buffer.force();
        buffer = dataChanell.map(FileChannel.MapMode.READ_WRITE, prev, SIZE);
        buffer.putLong(l);
        buffer.force();
    }

    public Long[] getPositions(String firstLetter) throws IOException {
        ArrayList<Long> lst = new ArrayList<Long>();
        long next = byteMap[abc.indexOf(firstLetter)];
        while(next != 0L){
            MappedByteBuffer buffer = dataChanell.map(FileChannel.MapMode.READ_ONLY, next, SIZE * 2);
            next = buffer.getLong();
            lst.add(buffer.getLong());
        }
        return (Long[]) lst.toArray(new Long[lst.size()]);
    }

    public static void main(String[] args) throws IOException {
        ABCLinkedList lst = new ABCLinkedList(new File(".index"), new EnglishOneLetterABC());
        lst.addPossition("a", 100);
        lst.addPossition("a", 101);
        lst.addPossition("a", 102);
        lst.addPossition("a", 103);
        lst.addPossition("a", 103);
        lst.addPossition("a", 103);
        lst.addPossition("a", 103);

        lst.addPossition("a", 1076);
        lst.addPossition("b", 104);
        for(long l: lst.getPositions("a")){
            System.out.println(l);
        }
    }
}
